home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / MIDI / Euterpe_Installation / Euterpe / Developer / fxdemo.c < prev    next >
C/C++ Source or Header  |  1998-06-24  |  20KB  |  696 lines

  1. /* FXDEMO
  2.  * A simple example for an EFFECTSPROCESSOR xapp application
  3.  * Author : Dominique Lorre
  4.  * $Id$
  5.  */
  6.  
  7. #include <exec/types.h>
  8. #include <exec/memory.h>
  9. #include <exec/semaphores.h>
  10. #include <intuition/gadgetclass.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14.  
  15. #include <proto/exec.h>
  16. #include <proto/dos.h>
  17. #include <proto/graphics.h>
  18. #include <proto/intuition.h>
  19. #include <proto/gadtools.h>
  20. #include <clib/macros.h>
  21.  
  22. #include "/xappmsg.h"
  23. //#include "mydebug.h"
  24.  
  25.  
  26. struct FXNode*      n ;
  27. struct List*        l ;
  28. struct Window*      xappwin ;
  29. struct Gadget*      glist ;
  30. struct Gadget*      gad ;
  31. APTR                vi ;
  32. struct Screen       *ps ;
  33. BOOL                winopen ;
  34.  
  35. struct MsgPort*    MyPort ;
  36. struct MsgPort*    XAppPort ;
  37. struct MsgPort*    replyPort ;
  38.  
  39. struct Hook        FXProcessor ;
  40. char                MyPortName[XAPPNAMELENGTH] ;
  41. APTR                xHandle ;
  42.  
  43. struct TagItem ti[] = {
  44.     {XAPP_Name,     (ULONG)"FX-DEMO"},
  45.     {XAPP_PortName, (ULONG)MyPortName},
  46.     {XAPP_Type,     (ULONG)XAPPTYP_EFFECTSPROCESSOR},
  47.     {FX_Hook,       (ULONG)&FXProcessor},
  48.     {TAG_DONE}
  49. };
  50.  
  51. struct TagItem th[] = {
  52.     {XAPP_Handle,   NULL},
  53.     {TAG_DONE}
  54. };
  55.  
  56. struct fxDemoData {
  57.     struct SignalSemaphore *fxd_Semaphore ;
  58.     LONG                    fxd_Len ;
  59.     WORD                    fxd_Repeat ;
  60.     WORD                    fxd_Variation ;
  61.     WORD                    fxd_Volume ;
  62.     BOOL                    fxd_ByPass ;
  63. } fData ;
  64.  
  65. struct SignalSemaphore *MySemaphore ;
  66.  
  67. static ULONG winsig, msig, signal ;
  68. BOOL fin  ;
  69. #define HIGHPRI 21
  70.  
  71. struct XAppMsg  *xmsg, *replymsg, *emsg ;
  72.  
  73. extern __stdargs ULONG HookEntry() ;
  74.  
  75. VOID main(VOID) ;
  76. BOOL InitAll(void) ;
  77. BOOL CloseAll(WORD level) ;
  78. void ProcessEvents(void) ;
  79. BOOL InitWin(void) ;
  80. BOOL CloseWin(WORD level) ;
  81. void ProcessWinEvents(void) ;
  82. VOID StripWindow(struct Window *win) ;
  83. VOID StripIntuiMessages( struct MsgPort *mp, struct Window *win ) ;
  84. VOID StripMessages( struct MsgPort *mp ) ;
  85.  
  86. ULONG __saveds __asm FX(register __a0 struct Hook *h, 
  87.                         register __a2 APTR Object, 
  88.                         register __a1 struct FXParams *fp) ;
  89.  
  90. /****** fxdemo.c/FX ********************************************************
  91. *
  92. *   NAME
  93. *   FX -- Hook function for effects processing
  94. *
  95. *   SYNOPSIS
  96. *   result = FX(h, Object, fp)
  97. *   ULONG __stdargs FX(struct Hook *, APTR, struct FXParams *)
  98. *
  99. *   FUNCTION
  100. *   This is the Hook function that will be invoked by Euterpe when processing
  101. *   events for effects.
  102. *
  103. *   INPUTS
  104. *   h       The Hook initialized by this module
  105. *   Object  Currently NULL
  106. *   fp      A FXParams structure described in xappmsg.h
  107. *
  108. *   RESULTS
  109. *   result  1 if everything ok and 0 if failure (other effects will be 
  110. *   skipped)
  111. *
  112. *   NOTES
  113. *   All the new events have to be placed on the same List, the best way
  114. *   to do this is to use exec.library/AddHead(). Do NOT expect the list
  115. *   to be sorted by time since effects might be chained. This function
  116. *   will be called in the heart of a realtime process running at a high
  117. *   priority (actually 21), so slow functions involving disk access, 
  118. *   keyboard input or the like must be invoked externally, by signalling.
  119. *   If your window is providing parameters, a Semaphore protection
  120. *   will be needed.
  121. *   NEVER EVER INSERT NOTEOFF EVENTS IN THE LIST
  122. *   Inserting a NoteOff is a bad idea because these events must be linked to 
  123. *   the correct NoteOn. For the control of NoteOff, use the x_Len field which 
  124. *   set the duration of a NoteOn and the x_Data[3] field which set the 
  125. *   velocity of the released note.
  126. *   NoteOff events will be inserted by Euterpe at the end of the FX parsing.
  127. *   NoteOn with x_Len = 0 are subject to crashes
  128. *   DO NOT EXPECT TO UNDERSTAND ALL EVENTS
  129. *   Events will be documented in the future because some are really special 
  130. *   such as tempochanges. For allowing your effect to work in the future, just
  131. *   keep the unknowned events unchanged. You can of course modify their pos
  132. *   but timesig events might be moved by Euterpe at the beginning of a 
  133. *   measure.
  134. *   DO NOT MAKE ANY ASSUMPTIONS ON WHAT WILL BE DONE WITH THIS EFFECT
  135. *   If you can. Because the effects might be modified in the future
  136. *   to operate on input flow, to write themselves to a track or even to be 
  137. *   lended as services to other tasks.
  138. *   SEE ALSO
  139. *   utility/hooks.h utility.library/CallHookPkt
  140. ****************************************************************************
  141. *
  142. */
  143.  
  144. ULONG __saveds __asm FX(register __a0 struct Hook *h, 
  145.                         register __a2 APTR Object, 
  146.                         register __a1 struct FXParams *fp)
  147. {
  148. struct FXNode       *n, *c, *s ;
  149. struct fxDemoData   *fxd ;
  150. UBYTE type ;
  151. LONG    val, r ;
  152.  
  153.     fxd = (struct fxDemoData *)h->h_Data ;
  154.  
  155.     // Semaphore protection is a must if you want to allow the user
  156.     // to modify the parameters while playing.
  157.  
  158.     ObtainSemaphore(fxd->fxd_Semaphore) ;
  159.  
  160.     if (!IsListEmpty((struct List *)fp->fp_List)) {
  161.  
  162.         // if we are the first effect the list will contain one event
  163.         // the linked effects will found what has been put by their
  164.         // predecessors
  165.  
  166.         n = (struct FXNode *)fp->fp_List->mlh_Head ;
  167.         while (n->x_Node.mln_Succ) {
  168.             s = (struct FXNode *)n->x_Node.mln_Succ ;
  169.             if (!fxd->fxd_ByPass) {
  170.                 type = n->x_Data[0] & 0xF0 ;
  171.                 // This is a noteon
  172.                 if (type == 0x90) {
  173.                     // Note transposition
  174.                     val = n->x_Data[1] + fxd->fxd_Variation ;
  175.                     n->x_Data[1] = (val > 0) ? MIN(val, 0x7F) : 0 ;
  176.         
  177.                     for (r = 0; (r < fxd->fxd_Repeat); r++) {
  178.  
  179.                         // Since we are in a RealTime application
  180.                         // we do not lose time by doing some garbage
  181.                         // collection. This code is safe because the array
  182.                         // will be reset by Euterpe when a new event will
  183.                         // appear
  184.         
  185.                         fp->fp_Pos++ ;
  186.                         c = (fp->fp_Pos < fp->fp_Size) ? &(fp->fp_Array[fp->fp_Pos]) : NULL ;
  187.  
  188.                         if (c) { // We have the new event node
  189.                             c->x_Msg = n->x_Msg ; // fast copy of the data
  190.  
  191.                             if (fxd->fxd_Len>1) {
  192.                                 c->x_Pos = n->x_Pos + fxd->fxd_Len ;
  193.                                 c->x_Len = n->x_Len ;
  194.                                 if (n->x_Len > fxd->fxd_Len) {
  195.                                     n->x_Len = fxd->fxd_Len-1 ; // len > 0 !
  196.                                 }
  197.                             }
  198.                             // Volume handling
  199.                             if (fxd->fxd_Volume > 0) {
  200.                                 val = c->x_Data[2] * (fxd->fxd_Volume+1) ;
  201.                                 c->x_Data[2] = MIN(val, 0x7F) ;
  202.                                 val = c->x_Data[3] * (fxd->fxd_Volume+1) ;
  203.                                 c->x_Data[3] = MIN(val, 0x7F) ;
  204.                             }
  205.                             else if (fxd->fxd_Volume < 0) {
  206.                                 c->x_Data[2] /= -fxd->fxd_Volume+1 ;
  207.                                 c->x_Data[3] /= -fxd->fxd_Volume+1 ;
  208.                             }
  209.                             // Add to list
  210.                             // Keeping the list sorted might allow quicker
  211.                             // effects if the sorting operation is really fast
  212.                             AddHead((struct List *)fp->fp_List, (struct Node *)c) ;
  213.                         }
  214.                     }
  215.                 }
  216.                 
  217.             }
  218.             n = s ;
  219.         }
  220.     }
  221.     ReleaseSemaphore(fxd->fxd_Semaphore) ;
  222.     return 1 ;
  223. }
  224.  
  225. VOID main(VOID)
  226. {
  227. int retval ;
  228.  
  229.     if (InitAll()) {
  230.         ProcessEvents() ;
  231.         retval =  CloseAll(0)?RETURN_OK:RETURN_FAIL;
  232.     }
  233.     else
  234.         retval = RETURN_FAIL ;
  235.     exit(retval) ;
  236. }
  237.  
  238. /****** fxdemo.c/InitAll ***************************************************
  239. *
  240. *   NAME
  241. *   InitAll -- Main Initializations
  242. *
  243. *   SYNOPSIS
  244. *   success = InitAll()
  245. *   BOOL InitAll(void)
  246. *
  247. *   FUNCTION
  248. *       InitAll allocates all needed resources step by step and is responsible
  249. *       for the initialization of the communication with Euterpe. CloseAll will
  250. *       be called in case of failure.
  251. *
  252. *   INPUTS
  253. *       None
  254. *
  255. *   RESULTS
  256. *       success     TRUE if the initialization succeed, FALSE if not
  257. *
  258. *   BUGS
  259. *       This function has a weak point because it may fail if Euterpe is closing
  260. *       when this task is loading. Forbid()/Permit() might solve the problem.
  261. *       Anyway, under normal use effects will not be loaded when Euterpe is
  262. *       exiting and developers have been asked not to use Forbid(). If 
  263. *       someone has an idea...
  264. *
  265. *   SEE ALSO
  266. *       fxdemo.c/CloseAll
  267. ****************************************************************************
  268. *
  269. */
  270. BOOL InitAll(void)
  271. {
  272.     // First, create a ReplyPort for communication with Euterpe
  273.  
  274.     replyPort = CreateMsgPort() ;
  275.     if (!replyPort)
  276.         return CloseAll(1) ;
  277.  
  278.     // Now, initialize the Message
  279.  
  280.     if (xmsg = (struct XAppMsg *)AllocVec(sizeof(struct XAppMsg), MEMF_CLEAR|MEMF_PUBLIC)) {
  281.         xmsg->xm_Message.mn_Node.ln_Type = NT_MESSAGE ;
  282.         xmsg->xm_Message.mn_Length = sizeof( struct XAppMsg ) ;
  283.         xmsg->xm_Message.mn_ReplyPort = replyPort ;
  284.     }
  285.     else
  286.         return CloseAll(2) ;
  287.  
  288.     // Our private semaphore
  289.  
  290.     if (MySemaphore = (struct SignalSemaphore *)AllocVec(sizeof(struct SignalSemaphore), MEMF_CLEAR|MEMF_PUBLIC)) {
  291.         InitSemaphore(MySemaphore) ;
  292.     }
  293.     else
  294.         return CloseAll(3) ;
  295.  
  296.     // Parameters initialization
  297.     fData.fxd_Semaphore = MySemaphore ;
  298.     fData.fxd_Repeat = 2 ;
  299.     fData.fxd_Len = 192 ;
  300.     fData.fxd_Volume = -2 ;
  301.     fData.fxd_Variation = 12 ;
  302.     fData.fxd_ByPass = FALSE ;
  303.  
  304.     // Hook initialization
  305.     FXProcessor.h_Entry = (HOOKFUNC)FX ;
  306.     FXProcessor.h_SubEntry = NULL ;
  307.     FXProcessor.h_Data = &fData ;
  308.  
  309.     // Look at Euterpe's xapp port
  310.  
  311.     if (XAppPort = FindPort((UBYTE *)XAPPPORTNAME)) {
  312.         // Euterpe is here, let's register
  313.         xmsg->xm_Action = XAPPACT_ADD ;
  314.         xmsg->xm_Tags = ti ;
  315.         PutMsg(XAppPort, (struct Message *)xmsg);
  316.         WaitPort(replyPort) ;
  317.         replymsg = (struct XAppMsg *)GetMsg(replyPort) ;
  318.         // Euterpe has given us a name for our port
  319.         xHandle = replymsg->xm_Result ;
  320.         if (!xHandle)
  321.             return CloseAll(4) ;
  322.         th[0].ti_Data = (ULONG)xHandle ;
  323.     }
  324.     else
  325.         return CloseAll(4) ;
  326.  
  327.     // Now, create our Port with the name given by Euterpe 
  328.  
  329.     MyPort = CreatePort(MyPortName, NULL);
  330.  
  331.     // We are ready now, tell Euterpe how the init was
  332.  
  333.     xmsg->xm_Action = MyPort ? XAPPACT_INIT : XAPPACT_FAILURE ;
  334.     xmsg->xm_Tags = th ;
  335.     PutMsg(XAppPort, (struct Message *)xmsg);
  336.     WaitPort(replyPort) ;
  337.     replymsg = (struct XAppMsg *)GetMsg(replyPort) ;
  338.  
  339.     if (!MyPort)
  340.         return CloseAll(5) ;
  341.  
  342.      msig = 1 << MyPort->mp_SigBit ;
  343.      return TRUE ;
  344. }
  345. /****** fxdemo.c/CloseAll **************************************************
  346. *
  347. *   NAME
  348. *   CloseAll -- Deallocates the resources
  349. *
  350. *   SYNOPSIS
  351. *   success = CloseAll(level)
  352. *   BOOL CloseAll(WORD)
  353. *
  354. *   FUNCTION
  355. *       CloseAll() will deallocate all the successfully allocated resources
  356. *       
  357. *   INPUTS
  358. *       level   0 if normal deallocation or the step where allocation failed
  359. *
  360. *   RESULTS
  361. *       success TRUE if called with level=0 FALSE in other cases
  362. *
  363. ****************************************************************************
  364. *
  365. */
  366.  
  367. BOOL CloseAll(WORD level)
  368. {
  369.     switch(level) {
  370.         case 0:
  371.             DeletePort(MyPort) ;
  372.         case 5:
  373.         case 4:
  374.             FreeVec(MySemaphore) ;
  375.         case 3:
  376.             FreeVec(xmsg) ;
  377.         case 2:
  378.             DeleteMsgPort(replyPort) ;
  379.     }
  380.     return (BOOL) ( level ? FALSE : TRUE ) ;
  381. }
  382.  
  383. void ProcessEvents(void)
  384. {
  385. ULONG           sigmask ;
  386. BOOL            end ;
  387. enum XAppAction action ;
  388.  
  389.     end = winopen = FALSE ;
  390.  
  391.     while (!end) {
  392.         sigmask = msig ;
  393.         if (winopen) sigmask |= winsig ;
  394.         signal = Wait(sigmask) ;
  395.         if (signal & winsig) {
  396.             // A better way of doing this could be to place the semaphore
  397.             // calls at the beginning of each modification of the fData fields
  398.             ObtainSemaphore(MySemaphore) ;
  399.             ProcessWinEvents() ;
  400.             if (!winopen)
  401.                 CloseWin(0) ;
  402.             ReleaseSemaphore(MySemaphore) ;
  403.         }
  404.         if (signal & msig) {
  405.             while (emsg = (struct XAppMsg *)GetMsg(MyPort)) {
  406.                 action = emsg->xm_Action ;
  407.                 // Do not reply to a remove msg
  408.                 // since Euterpe do not wait for it
  409.                 if (action != XAPPACT_REMOVE)
  410.                     ReplyMsg((struct Message *)emsg) ;
  411.                 switch (action) {
  412.                     case XAPPACT_SHOW:
  413.                         if (!winopen && InitWin())
  414.                             winopen = TRUE ;
  415.                         break ;
  416.                     case XAPPACT_REMOVE:
  417.                         end = TRUE ;
  418.                     case XAPPACT_HIDE:
  419.                         if (winopen) {
  420.                             CloseWin(0) ;
  421.                         }
  422.                         break ;
  423.                 }
  424.             }
  425.         }
  426.     }
  427. }
  428.  
  429. LONG __saveds VolumeLevel(struct Gadget *g,  WORD level)
  430. {
  431. static char s[30] ;
  432. static char v[8] ;
  433.  
  434.     if (level < 0) {
  435.         stci_d(v, -level+1) ;
  436.         strcpy(s, "Divide Volume by ") ;
  437.         strcat(s, v) ;
  438.     }
  439.     else if (level > 0) {
  440.         stci_d(v, level+1) ;
  441.         strcpy(s, "Multiply Volume by ") ;
  442.         strcat(s, v) ;
  443.     }
  444.     else strcpy(s, "Keep Volume") ;
  445.     return (LONG)s ;
  446. }
  447.         
  448. BOOL InitWin(void)
  449. {      
  450. struct NewGadget ng ;
  451. UWORD winZoom[4] = { 50, 50, 300, 20 } ;
  452.  
  453.     ps = LockPubScreen((UBYTE *)"Euterpe") ; // Get the Euterpe public screen
  454.     if (!ps)
  455.         return CloseWin(1) ;
  456.  
  457.     winZoom[0] = winZoom[3] = ps->BarHeight ;  // cosmetic details
  458.  
  459.     vi = GetVisualInfo(ps, NULL) ;
  460.     if (!vi)
  461.         return CloseWin(2) ;
  462.  
  463.     glist = NULL ;
  464.     gad = CreateContext(&glist) ;
  465.     if (!gad)
  466.         return CloseWin(3) ;
  467.  
  468.     ng.ng_VisualInfo = vi ;
  469.     ng.ng_TextAttr = ps->Font ;
  470.  
  471.     ng.ng_TopEdge = ps->BarHeight + 8 ; // font adaptative method
  472.     ng.ng_LeftEdge =  20 ;
  473.     ng.ng_Width = 10 ;
  474.     ng.ng_Height = ng.ng_TextAttr->ta_YSize * 3 / 2 ;
  475.     ng.ng_GadgetID = 1 ;
  476.     ng.ng_GadgetText = (UBYTE *)"ByPass" ;
  477.     ng.ng_Flags = PLACETEXT_RIGHT ;
  478.  
  479.     gad  = CreateGadget(CHECKBOX_KIND, gad, &ng,
  480.         GTCB_Checked,   fData.fxd_ByPass,
  481.         TAG_DONE);
  482.  
  483.     if (!gad)
  484.         return CloseWin(4);
  485.  
  486.     ng.ng_TopEdge += ng.ng_Height + 8 ;
  487.     ng.ng_LeftEdge =  20 ;
  488.     ng.ng_Width = 128 ;
  489.     ng.ng_Height = 20 ;
  490.     ng.ng_GadgetID = 2 ;
  491.     ng.ng_Flags = PLACETEXT_RIGHT ;
  492.  
  493.     gad  = CreateGadget(SLIDER_KIND, gad, &ng,
  494.     GTSL_Min,           -64,
  495.     GTSL_Max,           64,
  496.     GTSL_Level,         fData.fxd_Variation,
  497.     GTSL_LevelFormat,   "Transposition : %ld",
  498.     GTSL_MaxLevelLen,   20,
  499.     GTSL_LevelPlace,    PLACETEXT_RIGHT,
  500.     GA_RelVerify,       TRUE,
  501.     TAG_DONE);
  502.     if (!gad)
  503.         return CloseWin(4);
  504.  
  505.     ng.ng_TopEdge += ng.ng_Height + 8 ;
  506.     ng.ng_GadgetID = 3 ;
  507.  
  508.     gad  = CreateGadget(SLIDER_KIND, gad, &ng,
  509.     GTSL_Min,           0,
  510.     GTSL_Max,           192*4,
  511.     GTSL_Level,         fData.fxd_Len,
  512.     GTSL_LevelFormat,   "Delay Length : %ld",
  513.     GTSL_MaxLevelLen,   19,
  514.     GTSL_LevelPlace,    PLACETEXT_RIGHT,
  515.     GA_RelVerify,       TRUE,
  516.     TAG_DONE);
  517.     if (!gad)
  518.         return CloseWin(4);
  519.  
  520.     ng.ng_TopEdge += ng.ng_Height + 8 ;
  521.     ng.ng_GadgetID = 4 ;
  522.     ng.ng_Flags = PLACETEXT_RIGHT ;
  523.  
  524.     gad  = CreateGadget(SLIDER_KIND, gad, &ng,
  525.     GTSL_Min,           0,
  526.     GTSL_Max,           10,
  527.     GTSL_Level,         fData.fxd_Repeat,
  528.     GTSL_LevelFormat,   "Repeat : %ld times",
  529.     GTSL_MaxLevelLen,   19,
  530.     GTSL_LevelPlace,    PLACETEXT_RIGHT,
  531.     GA_RelVerify,       TRUE,
  532.     TAG_DONE);
  533.     if (!gad)
  534.         return CloseWin(4);
  535.  
  536.     ng.ng_TopEdge += ng.ng_Height + 8 ;
  537.     ng.ng_GadgetID = 5 ;
  538.     ng.ng_Flags = PLACETEXT_RIGHT ;
  539.  
  540.     gad  = CreateGadget(SLIDER_KIND, gad, &ng,
  541.     GTSL_Min,           -8,
  542.     GTSL_Max,           8,
  543.     GTSL_Level,         fData.fxd_Volume,
  544.     GTSL_LevelFormat,   "%s",             /* Did you knew this trick ? :) */
  545.     GTSL_DispFunc,      VolumeLevel,
  546.     GTSL_MaxLevelLen,   25,
  547.     GTSL_LevelPlace,    PLACETEXT_RIGHT,
  548.     GA_RelVerify,       TRUE,
  549.     TAG_DONE);
  550.     if (!gad)
  551.         return CloseWin(4);
  552.  
  553.     /* Open a simple window */
  554.     xappwin = OpenWindowTags(NULL,
  555.     WA_Left,            50,
  556.     WA_Top,             ps->BarHeight,
  557.     WA_Width,           300,
  558.     WA_Height,          ng.ng_TopEdge + ng.ng_Height + 8, // font adaptative
  559.     WA_Title,           MyPortName,
  560.     WA_CloseGadget,     TRUE,
  561.     WA_DepthGadget,     TRUE,
  562.     WA_Gadgets,         glist,
  563.     WA_IDCMP,           IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW|
  564.                         CHECKBOXIDCMP|SLIDERIDCMP,
  565.     WA_DragBar,         TRUE,
  566.     WA_Activate,        TRUE,
  567.     WA_PubScreen,       ps,
  568.     WA_Zoom,            winZoom,
  569.     TAG_DONE) ;
  570.  
  571.     if (xappwin) {
  572.         GT_RefreshWindow(xappwin, NULL) ;
  573.         winsig = 1 << xappwin->UserPort->mp_SigBit ;
  574.         return TRUE ;
  575.     }
  576.     else
  577.         return CloseWin(5) ;
  578.  
  579. }
  580.  
  581. BOOL CloseWin(WORD level)
  582. {
  583.     winopen = FALSE ;
  584.     switch(level) {
  585.     case 0:
  586.         StripWindow(xappwin) ;
  587.         CloseWindow(xappwin) ;
  588.         xappwin = NULL ;
  589.         winsig = 0 ;
  590.     case 5:
  591.     case 4:
  592.         FreeGadgets(glist) ;
  593.     case 3:
  594.         FreeVisualInfo(vi) ;
  595.     case 2:
  596.         UnlockPubScreen(NULL, ps) ;
  597.     }
  598.     return (BOOL) ( level ? FALSE : TRUE ) ;
  599. }
  600.  
  601. void ProcessWinEvents(void)
  602. {
  603. ULONG                   classe ;
  604. UWORD                   code ;
  605. struct IntuiMessage*    imsg ;
  606. struct Gadget*          gad ;
  607.  
  608.     while (imsg = GT_GetIMsg(xappwin->UserPort)) {
  609.         classe = imsg->Class ;
  610.         code = imsg->Code ;
  611.         gad = (struct Gadget *)imsg->IAddress ;
  612.         GT_ReplyIMsg(imsg) ;
  613.         switch (classe) {
  614.         case IDCMP_REFRESHWINDOW:
  615.             GT_BeginRefresh(xappwin) ;
  616.             GT_EndRefresh(xappwin, TRUE) ;
  617.             break ;
  618.         case IDCMP_GADGETUP:
  619.             switch (gad->GadgetID) {
  620.             case 1:
  621.                 fData.fxd_ByPass = code ;
  622.                 break ;
  623.             case 2:
  624.                 fData.fxd_Variation = code ;
  625.                 break ;
  626.             case 3:
  627.                 fData.fxd_Len = code ;
  628.                 break ;
  629.             case 4:
  630.                 fData.fxd_Repeat = code ;
  631.                 break ;
  632.             case 5:
  633.                 fData.fxd_Volume = code ;
  634.                 break ;
  635.             }
  636.             break ;
  637.         case IDCMP_CLOSEWINDOW:
  638.             winopen = FALSE ;
  639.             break ;
  640.         }
  641.     }
  642. }
  643.  
  644. /* Useful C= functions */
  645.  
  646. VOID StripWindow(struct Window *win)
  647. {
  648.     Forbid();                                   
  649.     StripIntuiMessages(win->UserPort, win);
  650.     win->UserPort = NULL;
  651.     ModifyIDCMP(win, NULL);
  652.     Permit();                                   
  653. }
  654.  
  655. VOID    StripIntuiMessages( struct MsgPort *mp, struct Window *win )
  656.         {
  657.             struct IntuiMessage *msg;
  658.             struct Node *succ;
  659.  
  660.             msg = (struct IntuiMessage *) mp->mp_MsgList.lh_Head;
  661.  
  662.             while( succ =  msg->ExecMessage.mn_Node.ln_Succ ) {
  663.  
  664.                 if( msg->IDCMPWindow ==  win ) {
  665.  
  666.                     /* Intuition is about to free this message.
  667.                      * Make sure that we have politely sent it back.
  668.                      */
  669.                     Remove( (struct Node *)msg );
  670.  
  671.                     ReplyMsg( (struct Message *)msg );
  672.                 }
  673.  
  674.                 msg = (struct IntuiMessage *) succ;
  675.             }
  676.         }
  677.  
  678. /* Another one for a private MsgPort */
  679.  
  680. VOID    StripMessages( struct MsgPort *mp )
  681.         {
  682.             struct Message *msg;
  683.             struct Node *succ;
  684.  
  685.             msg = (struct Message *) mp->mp_MsgList.lh_Head;
  686.  
  687.             while( succ =  msg->mn_Node.ln_Succ ) {
  688.  
  689.                     Remove( (struct Node *)msg );
  690.  
  691.                     ReplyMsg( msg );
  692.  
  693.                 msg = (struct Message *) succ;
  694.             }
  695.         }
  696.